package chatroom

import (
    "gitee.com/zwx784533/zwx2018/app"
    "github.com/gorilla/websocket"
    "net/http"
    "encoding/json"
    "gitee.com/zwx784533/zwx2018/middleware"
    "gitee.com/zwx784533/zwx2018/model"
    "os"
)

type Room struct {
    users map[int]*websocket.Conn
}
type msg struct {
    MsgId  int `json:"msg_id"`
    MsgData interface{} `json:"msg_data"`
}
var upgrader = websocket.Upgrader{
    CheckOrigin: checkOrigin,
}
var globalRoom = Room{
    users: make(map[int]*websocket.Conn),
}
// 添加 websocket 的路由
func Run(r *app.Router) {
    r.GET("/websocket", handleWebsocket)
}

// 处理 websocket
func handleWebsocket(ct *app.Context)  {
    app.Info("[chatroom] connect")
    c, err := upgrader.Upgrade(ct.Writer, ct.Request, nil)
    if err != nil {
        app.Error("[chatroom] upgrade:", err)
        return
    }

    var curUid int
    for {
        mt, message, err := c.ReadMessage()
        if err != nil {
            app.Error("[chatroom] read message:", err)
            break
        }

        var _msg msg
        err = json.Unmarshal(message, &_msg)
        if err != nil {
            app.Error("[chatroom] error: ", err)
            break
        }
        app.Info("[chatroom] recv:", _msg)
        switch _msg.MsgId {
            case 1:
                token, ok := _msg.MsgData.(map[string]interface{})["token"].(string)
                if !ok {
                    break
                }
                uid := middleware.CheckToken(token)
                if uid <=0 {
                    break
                }
                curUid = uid
                globalRoom.Join(curUid, c)
                break
            case 3:
                if curUid == 0 {
                    app.Info("没登录")
                    c.WriteMessage(mt, []byte("尚未登录"))
                    break
                }
                globalRoom.broadcast(curUid, websocket.TextMessage, _msg)
                break
            default:
                c.WriteMessage(mt, message)
        }
    }

    if curUid != 0 {
        globalRoom.Leave(curUid)
    }
}

// 检查源头
func checkOrigin(r *http.Request) bool {
    return true // todo
}

// 广播消息
func (r *Room) broadcast(curUid int, mt int, message interface{})  {
    app.Info("[broadcast] curUid:", curUid, "pid=", os.Getpid())
    for uid, conn := range r.users {
        if uid == curUid {
            continue
        }
        jsonByte, _ := json.Marshal(message)
        err := conn.WriteMessage(mt, jsonByte)
        if err != nil {
            app.Error("[chatroom] broadcast uid=", uid, ",err=", err)
        }
    }
}

// 进入房间
func (r *Room) Join(curUid int, conn *websocket.Conn)  {
    _, ok := r.users[curUid]
    if ok {
        // 已经在房间内,要先关闭之前的连接
        r.Leave(curUid)
        return
    }
    r.users[curUid] = conn
    user, _ := model.GetUserData(curUid)
    message := app.Obj{"msg_id": 2, "msg_data": app.Obj{"user": user, "test": 1}}
    r.broadcast(curUid, websocket.TextMessage, message)
}

// 离开房间
func (r *Room) Leave(curUid int)  {
    curConn, ok := r.users[curUid]
    if !ok {
        app.Error("[chatroom] Leave room : ", curUid, " 不在房间内")
        return
    }
    curConn.Close()
    delete(r.users, curUid)
    user, _ := model.GetUserData(curUid)
    message := app.Obj{"msg_id": 4, "msg_data": app.Obj{"user": user}}
    r.broadcast(curUid, websocket.TextMessage, message)
}